﻿using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace ConsoleApp;

public class DemoXml
{
    public void Read()
    {
        string xmlString = "<root><element1>Value 1</element1><element2>Value 2</element2></root>";
 
        // 创建XmlDocument对象
        XmlDocument xmlDoc = new XmlDocument();
 
        try
        {
            // 加载XML字符串
            xmlDoc.LoadXml(xmlString);
 
            // 获取根节点
            XmlNode root = xmlDoc.DocumentElement;
 
            // 获取子节点的值
            var element1Value = root.SelectSingleNode("element1").InnerText;
            var element2Value = root.SelectSingleNode("element2").InnerText;
 
            // 输出结果
            Console.WriteLine($"element1: {element1Value}");
            Console.WriteLine($"element2: {element2Value}");
        }
        catch (XmlException e)
        {
            // XML解析错误处理
            Console.WriteLine($"XML解析错误：{e.Message}");
        }
    }

    public void Demo()
    {
        var data = XmlHelper.XmlDeserializeFromFile<Entity>(@"D:\Test.xml");
        
        
    }
}

/// <summary>
/// XML工具类
/// </summary>
public static class XmlHelper
{
    /// <summary>
    /// 将一个对象序列化为XML字符串。这个方法将不生成XML文档声明头。
    /// </summary>
    /// <param name="o">要序列化的对象</param>
    /// <returns>序列化产生的XML字符串</returns>
    public static string XmlSerializerObject(object o)
    {
        var encoding = Encoding.UTF8;
        var serializer = new XmlSerializer(o.GetType());
        using var stream = new MemoryStream();
        var settings = new XmlWriterSettings
        {
            Indent = true,
            NewLineChars = "\r\n",
            Encoding = encoding,
            OmitXmlDeclaration = true,
            IndentChars = "    "
        };

        var ns = new XmlSerializerNamespaces();
        ns.Add("", "");

        using (var writer = XmlWriter.Create(stream, settings))
        {
            serializer.Serialize(writer, o, ns);
            writer.Close();
        }
        //return Encoding.UTF8.GetString(stream.ToArray());

        stream.Position = 0;
        using (var reader = new StreamReader(stream, encoding))
        {
            return reader.ReadToEnd();
        }
    }

    private static void XmlSerializeInternal(Stream stream, object o, Encoding encoding)
    {
        var serializer = new XmlSerializer(o.GetType());

        var settings = new XmlWriterSettings
        {
            Indent = true,
            NewLineChars = "\r\n",
            Encoding = encoding,
            IndentChars = "    "
        };

        using var writer = XmlWriter.Create(stream, settings);
        serializer.Serialize(writer, o);
    }
    
    /// <summary>
    /// 将一个对象序列化为XML字符串
    /// </summary>
    /// <param name="o">要序列化的对象</param>
    /// <param name="encoding">编码方式</param>
    /// <returns>序列化产生的XML字符串</returns>
    public static string XmlSerialize(object o, Encoding encoding)
    {
        using var stream = new MemoryStream();
        XmlSerializeInternal(stream, o, encoding);

        stream.Position = 0;
        using var reader = new StreamReader(stream, encoding);
        return reader.ReadToEnd();
    }
    
    /// <summary>
    /// 将一个对象按XML序列化的方式写入到一个文件（采用UTF8编码）
    /// </summary>
    /// <param name="o">要序列化的对象</param>
    /// <param name="path">保存文件路径</param>
    public static void XmlSerializeToFile(object o, string path)
    {
        XmlSerializeToFile(o, path, Encoding.UTF8);
    }

    /// <summary>
    /// 将一个对象按XML序列化的方式写入到一个文件
    /// </summary>
    /// <param name="o">要序列化的对象</param>
    /// <param name="path">保存文件路径</param>
    /// <param name="encoding">编码方式</param>
    public static void XmlSerializeToFile(object o, string path, Encoding encoding)
    {
        using var file = new FileStream(path, FileMode.Create, FileAccess.Write);
        XmlSerializeInternal(file, o, encoding);
    }

    /// <summary>
    /// 从XML字符串流中反序列化对象
    /// </summary>
    /// <param name="stream">包含对象的XML字符串流</param>
    /// <param name="destType">要序列化的目标类型</param>
    /// <returns>反序列化得到的对象</returns>
    public static object XmlDeserialize(Stream stream, Type destType)
    {
        var mySerializer = new XmlSerializer(destType);
        using var sr = new StreamReader(stream);
        return mySerializer.Deserialize(sr);
    }

    /// <summary>
    /// 从XML字符串中反序列化对象
    /// </summary>
    /// <param name="s">包含对象的XML字符串</param>
    /// <param name="destType">要序列化的目标类型</param>
    /// <param name="encoding">编码方式</param>
    /// <returns>反序列化得到的对象</returns>
    public static object XmlDeserialize(string s, Type destType, Encoding encoding)
    {
        using var ms = new MemoryStream(encoding.GetBytes(s));
        return XmlDeserialize(ms, destType);
    }
    
    /// <summary>
    /// 从XML字符串中反序列化对象
    /// </summary>
    /// <typeparam name="T">结果对象类型</typeparam>
    /// <param name="s">包含对象的XML字符串</param>
    /// <returns>反序列化得到的对象</returns>
    public static T XmlDeserialize<T>(string s)
    {
        return (T)XmlDeserialize(s, typeof(T), Encoding.UTF8);
    }

    /// <summary>
    /// 读入一个文件，并按XML的方式反序列化对象。
    /// </summary>
    /// <typeparam name="T">结果对象类型</typeparam>
    /// <param name="path">文件路径</param>
    /// <returns>反序列化得到的对象</returns>
    public static T XmlDeserializeFromFile<T>(string path)
    {
        using var fs = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read);
        return (T)XmlDeserialize(fs, typeof(T));
    }

    /// <summary>
    /// 获取XML跟节点的值
    /// </summary>
    /// <param name="path">文件路径</param>
    /// <returns></returns>
    public static string XmlGetElementName(string path)
    {
        var xmlDoc = new XmlDocument();
        xmlDoc.Load(path);
        return xmlDoc.DocumentElement.Name;
    }
}

[XmlRoot("Entity")]
public class Entity
{

    [XmlAttribute("Id")]
    public Guid EntityId { get; set; }

    [XmlAttribute]
    public string Name { get; set; }

    [XmlAttribute]
    public string DisplayName { get; set; }

    [XmlElement("Status")]
    public StatusEntity StatusEntity { get; set; }

    //[XmlArrayItem("Attribute")]       //和[XmlType("Attribute")] 效果一样
    [XmlArray("Attributes")]
    public List<Attributes> Attributes { get; set; }

    [XmlElement("Tags")]
    public List<string> Tags { set; get; }

    [XmlIgnore]
    public string Name2 { get; set; }
}

[XmlRoot("Status")]
public class StatusEntity
{
    [XmlAttribute("StatusId")]
    public string Id { get; set; }

    [XmlText]
    //获取Status 节点的值
    public string Value { get; set; }
}

[XmlType("Attribute")]
public class Attributes
{

    [XmlElement("Id")]
    public Guid AttributeId { get; set; }

    [XmlAttribute("Type")]
    public string Type { get; set; }

    [XmlElement]
    public string Name { get; set; }
}